#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#define MAX_PATH_LENGTH 256

// 检查一个字符串是否是数字
int is_digit(const char *str) {
    while (*str) {
        if (!isdigit(*str)) return 0;
        str++;
    }
    return 1;
}

// 打印进程内存使用情况
void PrintMemoryInfo(int pid) {
    char path[MAX_PATH_LENGTH];
    snprintf(path, sizeof(path), "/proc/%d/statm", pid);
    FILE *fp = fopen(path, "r");

    if (fp == NULL) {
        perror("Error opening statm file");
        return;
    }

    // statm 文件包含以下字段:
    // size, resident, shared, text, lib, data, dt
    // 其中 size 是进程总的虚拟内存，resident 是常驻内存
    long size, resident;
    if (fscanf(fp, "%ld %ld", &size, &resident) != 2) {
        perror("Error reading statm file");
        fclose(fp);
        return;
    }

    fclose(fp);

    // 每个页面的大小，通常为 4KB
    long page_size = sysconf(_SC_PAGE_SIZE);

    // 输出内存信息
    printf("Process ID: %d\n", pid);
    printf("Total virtual memory: %ld KB\n", size * page_size / 1024); // 转为 KB
    printf("Resident memory: %ld KB\n", resident * page_size / 1024); // 转为 KB
}

// 遍历进程目录并打印内存信息
void EnumProcesses() {
    struct dirent *entry;
    DIR *dp = opendir("/proc");

    if (dp == NULL) {
        perror("Error opening /proc directory");
        return;
    }

    // 遍历 /proc 目录，查找进程
    while ((entry = readdir(dp)) != NULL) {
        // 只考虑数字目录，这些是进程 ID
        if (is_digit(entry->d_name)) {
            int pid = atoi(entry->d_name);
            PrintMemoryInfo(pid);
        }
    }

    closedir(dp);
}

int main() {
    EnumProcesses();
    return 0;
}
